package com.webflux.utils;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 滑动窗口算法
 *
 * @author: 王霄
 * @date: 2021/9/27 13:29
 **/
public class SlideWindow {

    private static final Map<String, LinkedList<Long>> windows = new HashMap<>(4);

    static Lock lock = new ReentrantLock();

    private final String key;
    private final long time;
    private final long count;

    /**
     * @param key   滑动窗口唯一key
     * @param time  滑动窗口时间轴大小
     * @param count 时间轴内允许通过的请求量
     */
    public SlideWindow(String key, long time, long count) {
        this.key = key;
        this.time = time;
        this.count = count;
    }

    public void pass() {
        lock.lock();
        try {
            while (true) {
                LinkedList<Long> list = windows.computeIfAbsent(key, k -> new LinkedList<>());
                long now = System.currentTimeMillis();
                if (list.size() < count) {
                    list.offerLast(now);
                    break;
                } else if (now - list.getFirst() > time) {
                    list.pollFirst();
                    list.offerLast(now);
                    break;
                } else {
                    Thread.sleep(100);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}
